// Copyright (c) ZeroC, Inc.

namespace Ice
{
    namespace servantLocator
    {
        namespace AMD
        {
            public sealed class ServantLocatorI : Ice.ServantLocator
            {
                public ServantLocatorI(String category)
                {
                    _category = category;
                    _deactivated = false;
                    _requestId = -1;
                }

                ~ServantLocatorI()
                {
                    lock (this)
                    {
                        test(_deactivated);
                    }
                }

                private static void test(bool b)
                {
                    if (!b)
                    {
                        throw new System.Exception();
                    }
                }

                public Ice.Object locate(Ice.Current current, out object cookie)
                {
                    lock (this)
                    {
                        test(!_deactivated);
                    }

                    test(current.id.category.Equals(_category) || _category.Length == 0);

                    if (current.id.name == "unknown")
                    {
                        cookie = null;
                        return null;
                    }

                    if (current.id.name == "invalidReturnValue" || current.id.name == "invalidReturnType")
                    {
                        cookie = null;
                        return null;
                    }

                    test(current.id.name == "locate" || current.id.name == "finished");
                    if (current.id.name == "locate")
                    {
                        exception(current);
                    }

                    //
                    // Ensure locate() is only called once per request.
                    //
                    test(_requestId == -1);
                    _requestId = current.requestId;

                    cookie = new Cookie();

                    return new TestI();
                }

                public void finished(Ice.Current current, Ice.Object servant, System.Object cookie)
                {
                    lock (this)
                    {
                        test(!_deactivated);
                    }

                    //
                    // Ensure finished() is only called once per request.
                    //
                    test(_requestId == current.requestId);
                    _requestId = -1;

                    test(current.id.category.Equals(_category) || _category.Length == 0);
                    test(current.id.name == "locate" || current.id.name == "finished");

                    if (current.id.name == "finished")
                    {
                        exception(current);
                    }

                    var co = (Cookie)cookie;
                    test(co.message() == "blahblah");
                }

                public void deactivate(string category)
                {
                    lock (this)
                    {
                        test(!_deactivated);

                        _deactivated = true;
                    }
                }

                private void exception(Ice.Current current)
                {
                    if (current.operation == "ice_ids")
                    {
                        throw new Test.TestIntfUserException();
                    }
                    else if (current.operation == "requestFailedException")
                    {
                        throw new Ice.ObjectNotExistException();
                    }
                    else if (current.operation == "unknownUserException")
                    {
                        throw new Ice.UnknownUserException("reason");
                    }
                    else if (current.operation == "unknownLocalException")
                    {
                        throw new Ice.UnknownLocalException("reason");
                    }
                    else if (current.operation == "unknownException")
                    {
                        throw new Ice.UnknownException("reason");
                    }
                    else if (current.operation == "userException")
                    {
                        throw new Test.TestIntfUserException();
                    }
                    else if (current.operation == "localException")
                    {
                        throw new Ice.SocketException();
                    }
                    else if (current.operation == "csException")
                    {
                        throw new System.Exception("message");
                    }
                    else if (current.operation == "unknownExceptionWithServantException")
                    {
                        throw new Ice.UnknownException("reason");
                    }
                    else if (current.operation == "impossibleException")
                    {
                        throw new Test.TestIntfUserException(); // Yes, it really is meant to be TestIntfException.
                    }
                    else if (current.operation == "intfUserException")
                    {
                        throw new Test.TestImpossibleException(); // Yes, it really is meant to be TestImpossibleException.
                    }
                    else if (current.operation == "asyncResponse")
                    {
                        throw new Test.TestImpossibleException();
                    }
                    else if (current.operation == "asyncException")
                    {
                        throw new Test.TestImpossibleException();
                    }
                }

                private bool _deactivated;
                private string _category;
                private int _requestId;
            }
        }
    }
}
